# Notes CMakeUtils.cmake

# 获取目录下的所有子目录
function(get_all_subdirs #
         _dir_in #
         _list_out #
)
  file(GLOB __tmp_list "${ARGV0}/*")
  set(__tmp_dirs)
  foreach(dir ${__tmp_list})
    if(IS_DIRECTORY ${dir})
      get_filename_component(filename ${dir} NAME)
      set(__tmp_dirs ${__tmp_dirs} ${filename})
    endif()
  endforeach()
  set(${ARGV1}
      ${__tmp_dirs}
      PARENT_SCOPE)
endfunction()

# 获取目录下的所有资源文件
function(get_all_resources #
         _dir_in #
         _list_out #
)
  file(GLOB __tmp_list "${ARGV0}/*.rc" "${ARGV0}/*.qrc" "${ARGV0}/*.ui")
  set(${ARGV1}
      "${__tmp_list}"
      PARENT_SCOPE)
endfunction()

# 创建静态库
function(
  create_static_library #
  LIB_NAME #
  PREFIX #
  SOURCE #
  INCLUDE_DIRS #
  DEPENDENCY #
  LINK_LIBS #
  COMPILE_DEFINITIONS #
)
  add_library(${LIB_NAME}_internal STATIC ${SOURCE})
  add_library(${PREFIX}::${LIB_NAME} ALIAS ${LIB_NAME}_internal)
  target_include_directories(${LIB_NAME}_internal PRIVATE ${INCLUDE_DIRS})

  if(DEPENDENCY)
    add_dependencies(${LIB_NAME}_internal ${DEPENDENCY})
  endif()

  if(LINK_LIBS)
    target_link_libraries(${LIB_NAME}_internal PRIVATE ${LINK_LIBS})
  endif()

  if(COMPILE_DEFINITIONS)
    # scope is PUBLIC so these definitions are propagated
    target_compile_definitions(${LIB_NAME}_internal
                               PRIVATE ${COMPILE_DEFINITIONS})
  endif()

  # 在 Visual Studio 中将库放入 Libs 文件夹
  set_property(TARGET ${LIB_NAME}_internal PROPERTY FOLDER "Libs")
endfunction()

# 创建 exe 程序
function(
  create_app #
  APP_NAME #
  PREFIX #
  SOURCE #
  INCLUDE_DIRS #
  DEPENDENCY #
  LINK_LIBS #
  COMPILE_DEFINITIONS #
)
  if(BUILD_EXAMPLES)
    set(APP_NAME ${PREFIX}_${APP_NAME})
    add_executable(${APP_NAME} ${SOURCE})
    target_include_directories(${APP_NAME} PRIVATE ${INCLUDE_DIRS})

    if(DEPENDENCY)
      add_dependencies(${APP_NAME} ${DEPENDENCY})
    endif()

    if(LINK_LIBS)
      target_link_libraries(${APP_NAME} PRIVATE ${LINK_LIBS})
    endif()

    if(COMPILE_DEFINITIONS)
      target_compile_definitions(${APP_NAME} PRIVATE ${COMPILE_DEFINITIONS})
    endif()

    # 在 Visual Studio 中将程序放入 Apps 文件夹
    set_property(TARGET ${APP_NAME} PROPERTY FOLDER "Apps")
  endif()
endfunction()

# 创建测试程序
function(
  create_test #
  TEST_NAME #
  PREFIX #
  SOURCE #
  INCLUDE_DIRS #
  DEPENDENCY #
  LINK_LIBS #
  COMPILE_DEFINITIONS #
)
  if(BUILD_TESTS)
    set(TEST_NAME ${PREFIX}_${TEST_NAME})
    add_executable(${TEST_NAME} ${SOURCE})
    target_include_directories(${TEST_NAME} PRIVATE ${INCLUDE_DIRS})
    target_link_libraries(${TEST_NAME} PRIVATE ${LINK_LIBS} gtest gtest_main)
    gtest_discover_tests(${TEST_NAME})
    add_custom_target(gtest-filter COMMAND $<TARGET_FILE:${TEST_NAME}>
                                           --gtest_filter="*${filter}*")

    if(DEPENDENCY)
      add_dependencies(${TEST_NAME} ${DEPENDENCY})
    endif()

    if(LINK_LIBS)
      target_link_libraries(${TEST_NAME} PRIVATE ${LINK_LIBS})
    endif()

    if(COMPILE_DEFINITIONS)
      target_compile_definitions(${TEST_NAME} PRIVATE ${COMPILE_DEFINITIONS})
    endif()

    # 在 Visual Studio 中将测试程序放入 tests 文件夹
    set_property(TARGET ${TEST_NAME} PROPERTY FOLDER "tests")
  endif()
endfunction()

# 复制动态库
function(copy_dll #
         TARGET_NAME #
         LINK_DLLS #
)
  file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Debug)
  file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release)

  # 注意使用 PRE_BUILD，在 Target 构建之前执行，否则构建失败则不会复制
  add_custom_command(
    TARGET ${TARGET_NAME}
    PRE_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LINK_DLLS}
            ${CMAKE_CURRENT_BINARY_DIR}/Debug
    COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LINK_DLLS}
            ${CMAKE_CURRENT_BINARY_DIR}/Release)
endfunction()
